#include "R_Datasource.h"
#include "Datasource_Wrap.h"
#include "R_Datasource_S4.h"
#include "R_S.h"
#include "R_Geometry_S4.h"
#include "Rinternals.h"

namespace RSuperMap{
	
	RcppExport SEXP R_Datasource_open(SEXP server, SEXP driver, SEXP database, SEXP alias, SEXP user, SEXP password,
		SEXP enType)
	{
		BEGIN_RCPP
			SEXP __result = NULL;

		string strServer = RTools::as_str(server);
		string strDriver = RTools::as_str(driver);
		string strDatabase = RTools::as_str(database);
		string strAlias = RTools::as_str(alias);
		string strUser = RTools::as_str(user);
		string strPassword = RTools::as_str(password);
		string strType = RTools::as_str(enType);

		void* pDatasource = Datasource_wrap_open(strServer.c_str(), strDatabase.c_str(), strDriver.c_str(),
			strAlias.c_str(), strUser.c_str(), strPassword.c_str(), strType.c_str());

		if(pDatasource != NULL)
		{
			__result = Rcpp::wrap(S4_Datasource((UGC::UGDataSource*)pDatasource));
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}


	RcppExport SEXP R_Datasource_create(SEXP server, SEXP driver, SEXP database, SEXP alias, SEXP user, SEXP password, SEXP enType)
	{
		BEGIN_RCPP
			SEXP __result = NULL;

		string strServer = RTools::as_str(server);
		string strDriver = RTools::as_str(driver);
		string strDatabase = RTools::as_str(database);
		string strAlias = RTools::as_str(alias);
		string strUser = RTools::as_str(user);
		string strPassword = RTools::as_str(password);
		string strType = RTools::as_str(enType);

		void* pDatasource = Datasource_wrap_create(strServer.c_str(), strDatabase.c_str(), strDriver.c_str(),
			strAlias.c_str(), strUser.c_str(), strPassword.c_str(), strType.c_str());

		if(pDatasource != NULL)
		{
			__result = Rcpp::wrap(S4_Datasource((UGC::UGDataSource*)pDatasource));
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasoruce_Del_Dt(SEXP pointer, SEXP name)
	{
		BEGIN_RCPP
			SEXP __result = Rcpp::wrap("datasets failed");
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			const char* pName = RTools::as_str(name).c_str();
		    bool bDel =  Datasource_wrap_del_dataset(pDatasource, pName);
			__result = Rcpp::wrap<bool>(bDel);
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasource_close(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			Datasource_wrap_close(pDatasource);
			pDatasource = NULL;
			__result = Rcpp::wrap<bool>(TRUE);
		}
		else
		{
			__result = Rcpp::wrap<bool>(FALSE);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasource_datasets(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result = Rcpp::wrap("datasets failed");
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			UGint nCount = Datasource_wrap_count(pDatasource);
			if(nCount > 0)
			{
				UGlong* pHandle = new UGlong[nCount];
				if(Datasource_wrap_datasets(pDatasource, pHandle))
				{
					GenericVector datasets(nCount);
					for(UGint i=0; i<nCount; i++)
					{
						UGDataset* pDataset = (UGDataset*)(pHandle[i]);
						if(Dataset_wrap_is_vector(pDataset))
						{
							datasets[i] = S4_DatasetVector((UGC::UGDatasetVector*)(pDataset));
						}
						else if(Dataset_wrap_is_raster(pDataset))
						{
							datasets[i] = S4_DatasetRaster((UGC::UGDatasetRaster*)(pDataset));
						}
						else
						{
							datasets[i] = S4_Dataset((UGC::UGDataset*)pDataset);
						}
					}
					__result = Rcpp::wrap(datasets);
				}
				else
				{
					__result = Rcpp::wrap<bool>(false);
				}
				delete[] pHandle;
				pHandle = NULL;
			}
			else
			{
				__result = Rcpp::wrap<Rcpp::GenericVector>(0);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Dataset_name(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			char* pName = Dataset_wrap_name((void*)pDataset);
			__result = RTools::wrap_str(pName);
			wrap_delete_primitive_ary(pName);
			pName = NULL;
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;

		END_RCPP
	}

	RcppExport SEXP R_Dataset_type(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			char* pName = Dataset_wrap_type((void*)pDataset);	
			string strName(pName);
			__result = Rcpp::wrap(strName);
			wrap_delete_primitive_ary(pName);
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}
	
	RcppExport SEXP R_DatasetVector_query_ids(SEXP pointer, SEXP ids, SEXP idField, SEXP hasGeometry)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDatasetVector* pdataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pdataset != NULL)
		{
			Rcpp::IntegerVector idsVector = Rcpp::as<Rcpp::IntegerVector>(ids);
			UGint* pIDs = NULL;
			
			if(idsVector.size() > 0)
			{
				pIDs = new UGint[idsVector.size()];
				for(UGint i=0; i<idsVector.size(); i++)
				{
					pIDs[i] = idsVector[i];
				}
			}

			bool bHasGeometry = Rcpp::as<bool>(hasGeometry);
			
			string strIDField = RTools::as_str(idField);
			const char* pIDField = strIDField.c_str();

			Wrap_Records resultRecords;
			if(DatasetVector_wrap_query_ids(pdataset, pIDs, idsVector.size(), pIDField, resultRecords, bHasGeometry))
			{
				__result = WrapQueryResult(resultRecords);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
			if(pIDs != NULL)
			{
				delete[] pIDs;
				pIDs = NULL;
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP WrapFieldValue(Wrap_Value* pValue)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		if(pValue != NULL)
		{
			UGVariant::VarType vtype = pValue->vType;
			switch (vtype)
			{
			case OGDC::OgdcVariant::Null:
				break;
			case OGDC::OgdcVariant::Byte:
				__result = Rcpp::wrap<UGuchar>(pValue->vValue.bVal);
				break;
			case OGDC::OgdcVariant::Short:
				__result = Rcpp::wrap<UGshort>(pValue->vValue.sVal);
				break;
			case OGDC::OgdcVariant::Integer:
				__result = Rcpp::wrap<UGint>(pValue->vValue.iVal);
				break;
			case OGDC::OgdcVariant::Long:
				__result = Rcpp::wrap<UGdouble>((UGdouble)(pValue->vValue.lVal));
				break;
			case OGDC::OgdcVariant::Float:
				__result = Rcpp::wrap<UGfloat>(pValue->vValue.fVal);
				break;
			case OGDC::OgdcVariant::Double:
				__result = Rcpp::wrap<UGdouble>(pValue->vValue.dVal);
				break;
			case OGDC::OgdcVariant::Time:
			case OGDC::OgdcVariant::String:
			case OGDC::OgdcVariant::Date:
			case OGDC::OgdcVariant::TimeStamp:
				{
					__result = RTools::wrap_str(pValue->vValue.pValue);
				}
				break;
			case OGDC::OgdcVariant::Binary:
				break;
			case OGDC::OgdcVariant::Boolean:
				__result = Rcpp::wrap<bool>(pValue->vValue.bVal);
				break;
			default:
				break;
			}
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_query(SEXP pointer, SEXP filter, SEXP groupDs, SEXP hasGeometry, SEXP order, SEXP fields)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDatasetVector* pdataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pdataset != NULL)
		{
			string strFilter;
			if(filter != NULL)
			{
				 strFilter = RTools::as_str(filter);
			}
			string strGroupBy;
			if(groupDs != NULL)
			{
				strGroupBy = RTools::as_str(groupDs);
			}

			string strOrderBy;
			if(order != NULL)
			{
				strOrderBy = RTools::as_str(order);
			}
			bool bHasGeometry = Rcpp::as<bool>(hasGeometry);
			char const** pFields = NULL;
			int nFieldCount = 0;
			if(fields != NULL)
			{
				StringVector aryFields = Rcpp::as<StringVector>(fields);
				if(aryFields.size() > 0)
				{
					pFields = new char const*[aryFields.size()];
					for(int i=0; i<aryFields.size(); i++)
					{
						pFields[i] = RTools::copy_str(aryFields[i]);
					}
					nFieldCount = aryFields.size();
				}
			}

			Wrap_Records resultRecords;
			if(DatasetVector_wrap_query(pdataset, strFilter.c_str(), strGroupBy.c_str(), strOrderBy.c_str(), pFields, nFieldCount, bHasGeometry, resultRecords))
			{
				__result = WrapQueryResult(resultRecords);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}

			for(int i=0; i<nFieldCount; i++)
			{
				wrap_delete_char_ary(pFields[i]);
			}
			if(pFields != NULL)
			{
				delete[] pFields;
				pFields  = NULL;
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}

		return __result;
		END_RCPP
	}
	
	RcppExport SEXP WrapQueryResult(Wrap_Records& resultRecords)
	{
		SEXP __result;

		UGint nValidCount = 0;
		for(UGint i=0; i<resultRecords.nCount; i++)
		{
			if(resultRecords.pFeature[i] != NULL) 
			{
				nValidCount++;
			}
		}
		Rcpp::GenericVector results(nValidCount);
		UGint nIndex = 0;
		for(UGint i=0; i<resultRecords.nCount; i++)
		{
			if(resultRecords.pFeature[i] != NULL)
			{
				Rcpp::GenericVector feature(1);
				Wrap_Feature* pFeature = resultRecords.pFeature[i];

				if(pFeature->pGeo != NULL)
				{
					UGint nGeoType = Geometry_wrap_getType(pFeature->pGeo);
					if(nGeoType == 1)
					{
						feature[0] = S4_GeoPoint((UGGeoPoint*)pFeature->pGeo);
					}
					else if(nGeoType == 3)
					{
						feature[0] = S4_GeoLine((UGGeoLine*)pFeature->pGeo);
					}
					else if(nGeoType == 5)
					{
						feature[0] = S4_GeoRegion((UGGeoRegion*)pFeature->pGeo);
					}
					else
					{
						feature[0] = S4_Geometry((UGGeometry*)pFeature->pGeo);
					}
				}
				else
				{
					feature[0] = Rcpp::wrap(0);
				}

				if(pFeature->nFieldCount > 0)
				{
					for(UGint j=0; j<pFeature->nFieldCount; j++)
					{
						Wrap_Field* pField = pFeature->pFields[j];
						if(pField != NULL)
						{
							char* pName = pField->name;
							std::string name(pName);
							
							Wrap_Value* pValue = pField->value;
							feature[name] = WrapFieldValue(pValue);
							if(pValue->vType ==  OgdcVariant::Time ||
								pValue->vType ==  OgdcVariant::String ||
								pValue->vType == OgdcVariant::Date||
								pValue->vType == OgdcVariant::TimeStamp)
							{
								wrap_delete_char_ary(pValue->vValue.pValue);
							}
							wrap_delete_primitive(pValue);
							wrap_delete_primitive(pName);
							wrap_delete_primitive(pField);
						}
					}
					wrap_delete_primitive_ary(pFeature->pFields);
				}

				wrap_delete_primitive(pFeature);
				results[nIndex] = feature;
				nIndex ++;
			}
		}
		wrap_delete_primitive_ary(resultRecords.pFeature);
		__result = Rcpp::wrap(results);
		return __result;
	}

	RcppExport SEXP R_Dataset_open(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			UGbool bOpen = Dataset_wrap_open(pDataset);
			__result = Rcpp::wrap<bool>(bOpen);
		}
		else
		{
			__result = Rcpp::wrap<bool>(FALSE);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Dataset_bounds(SEXP  pointer)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			UGdouble rc[4];
			if(Dataset_wrap_getBounds(pDataset, rc))
			{
				Rcpp::NumericVector xys(4);
				xys[0] = rc[0];
				xys[1] = rc[1];
				xys[2] = rc[2];
				xys[3] = rc[3];
				__result = Rcpp::wrap(xys);
				return __result;
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_query_bounds(SEXP pointer, SEXP bounds, SEXP filter, SEXP order)
	{
		BEGIN_RCPP
			SEXP __result = NULL;

		UGDatasetVector* pdataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pdataset != NULL)
		{
			string strFilter;
			if(filter != NULL)
			{
				strFilter = RTools::as_str(filter);
			}

			string strOrderBy;
			if(order != NULL)
			{
				strOrderBy = RTools::as_str(order);
			}

			Rcpp::NumericVector aryBounds = Rcpp::NumericVector(bounds);
			UGdouble aryB[4];
			aryB[0] = aryBounds[0];
			aryB[1] = aryBounds[1];
			aryB[2] = aryBounds[2];
			aryB[3] = aryBounds[3];

			Wrap_Records resultRecords;
			if(DatasetVector_wrap_query_bounds(pdataset, aryB, strFilter.c_str(), strOrderBy.c_str(), resultRecords))
			{
				__result = WrapQueryResult(resultRecords);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_query_geometry(SEXP pointer, SEXP queryGeo, SEXP filter, SEXP order, SEXP mode)
	{
		BEGIN_RCPP
			SEXP __result = NULL;

		UGDatasetVector* pdataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pdataset != NULL)
		{
			string strFilter;
			if(filter != NULL)
			{
				strFilter = RTools::as_str(filter);
			}
			string strMode;
			if(mode != NULL)
			{
				strMode = RTools::as_str(mode);
			}

			string strOrderBy;
			if(order != NULL)
			{
				strOrderBy = RTools::as_str(order);
			}

			UGGeometry* pGeo = (UGGeometry*) EXTPTR_PTR(queryGeo);

			Wrap_Records resultRecords;
			if(DatasetVector_wrap_query_geometry(pdataset, pGeo, strFilter.c_str(), strOrderBy.c_str(), strMode.c_str(), resultRecords))
			{
				__result = WrapQueryResult(resultRecords);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_fieldInfos(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDatasetVector* pdataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pdataset != NULL)
		{
			Wrap_FieldInfos fieldInfos;
			fieldInfos.nCount = 0;
			fieldInfos.pFieldInfo = NULL;
			if(DatasetVector_wrap_getFieldInfos(pdataset,fieldInfos))
			{
				Rcpp::GenericVector res(fieldInfos.nCount);
				int k=0;
				for(UGint i=0; i<fieldInfos.nCount; i++)
				{
					Wrap_FieldInfo* pField = fieldInfos.pFieldInfo[i];
					if(pField == NULL)
					{
						continue;
					}
					Rcpp::GenericVector field;
					field["name"] = RTools::wrap_str(pField->name);
					field["default"] = RTools::wrap_str(pField->defaultValue);
					field["caption"] = RTools::wrap_str(pField->caption);
					field["type"] = RTools::wrap_str(pField->type);
					field["systemField"] = pField->bSystem;
					field["required"] = pField->bRequired;
					field["maxLength"] = pField->maxLength;
					res[k] = field;
					k++;
				}
				__result = Rcpp::wrap(res);
				wrap_delete_FieldInfos(fieldInfos);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasource_available_name(SEXP pointer, SEXP name)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			string strName = RTools::as_str(name);
			char* pAName = Datasource_wrap_valid_dt_Name(pDatasource, strName.c_str());
			__result = RTools::wrap_str(pAName);
			wrap_delete_primitive_ary(pAName);
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasource_create_dtv(SEXP pointer, SEXP name, SEXP dtType, SEXP fields)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			string strName = RTools::as_str(name);
			string strType = RTools::as_str(dtType);


			Rcpp::GenericVector fieldInfos = Rcpp::as<Rcpp::GenericVector>(fields);
			int count = fieldInfos.size();
			Wrap_FieldInfos wrapFieldInfos;
			wrapFieldInfos.nCount = 0;
			if(count > 0)
			{
				wrapFieldInfos.nCount = count;
				wrapFieldInfos.pFieldInfo = new Wrap_FieldInfo*[count];
				for(int i=0; i<count; i++)
				{
					Rcpp::GenericVector fieldInfo  = Rcpp::as<Rcpp::GenericVector>(fieldInfos[i]);
					Wrap_FieldInfo* pFieldInfo = new Wrap_FieldInfo();
					pFieldInfo->name  = RTools::copy_str(fieldInfo["name"]);
					pFieldInfo->type  = RTools::copy_str(fieldInfo["type"]);
					pFieldInfo->caption  = RTools::copy_str(fieldInfo["caption"]);
					pFieldInfo->defaultValue  = RTools::copy_str(fieldInfo["default"]);
					pFieldInfo->bRequired  = Rcpp::as<bool>(fieldInfo["required"]);
					pFieldInfo->bSystem  = Rcpp::as<bool>(fieldInfo["systemField"]);
					pFieldInfo->maxLength  =  Rcpp::as<int>(fieldInfo["maxLength"]);
					wrapFieldInfos.pFieldInfo[i] = pFieldInfo;
				}
			}
			

			UGC::UGDatasetVector* pDt = (UGC::UGDatasetVector*)Datasource_wrap_create_dtv(pDatasource, strName.c_str(), 
				strType.c_str(), wrapFieldInfos);
		
			if(wrapFieldInfos.nCount > 0)
			{
				for(int i=0; i<wrapFieldInfos.nCount; i++)
				{
					Wrap_FieldInfo* pF = wrapFieldInfos.pFieldInfo[i];
					wrap_delete_primitive_ary(pF->name);
					wrap_delete_primitive_ary(pF->caption);
					wrap_delete_primitive_ary(pF->type);
					wrap_delete_primitive_ary(pF->defaultValue);
					delete pF;
				}
				delete[] wrapFieldInfos.pFieldInfo;
			}

			if(pDt != NULL)
			{
				__result = Rcpp::wrap(S4_DatasetVector(pDt));
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_Datasource_alias(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			char* pAlias = Datasource_wrap_alias(pDatasource);
			if(pAlias != NULL)
			{
				__result = RTools::wrap_str(pAlias);
				wrap_delete_primitive_ary(pAlias);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP;
	}

	RcppExport SEXP R_DatasetVector_write(SEXP geos, SEXP fieldNames, SEXP fieldValues, SEXP dsPointer, SEXP name, SEXP datasetType)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDataSource* pDS = (UGDataSource*) EXTPTR_PTR(dsPointer);
		if(pDS != NULL)
		{
			string strDtName = RTools::as_str(name);
			string strDatasetType = RTools::as_str(datasetType);
			Rcpp::GenericVector aryGeos  = Rcpp::as<Rcpp::GenericVector>(geos);
			Rcpp::CharacterVector aryFieldName = Rcpp::as<Rcpp::CharacterVector>(fieldNames);
			Rcpp::GenericVector aryFieldValues = Rcpp::as<Rcpp::GenericVector>(fieldValues);
			R_xlen_t count = aryGeos.size();
			if(count > 0 && count != aryFieldValues.size())
			{
				__result = Rcpp::wrap<bool>(false);
			}
			else
			{
				Wrap_Geometrys wrapGeo;
				wrapGeo.pGeos  = new UGGeometry*[aryFieldValues.size()];
				wrapGeo.nCount = aryFieldValues.size();
				if(count >0 )
				{
					for(int i=0; i<count; i++)
					{
						wrapGeo.pGeos[i] = (UGGeometry*)EXTPTR_PTR(aryGeos[i]);
					}
				}
				else
				{
					for(int i=0; i<wrapGeo.nCount; i++)
					{
						wrapGeo.pGeos[i] = NULL;
					}
				}

				int nFieldCount = aryFieldName.size();
				char** pFieldName = new char*[nFieldCount];
				for(int i=0; i<nFieldCount; i++)
				{
					pFieldName[i] = RTools::copy_str(aryFieldName[i]);
				} 		
				char*** pFieldValues = new char**[wrapGeo.nCount];
				for(int i=0; i<wrapGeo.nCount; i++)
				{
					pFieldValues[i] = new char*[nFieldCount];
					Rcpp::CharacterVector aryFieldValue = Rcpp::as<Rcpp::CharacterVector>(aryFieldValues[i]);
					for(int j=0; j<nFieldCount; j++)
					{
						pFieldValues[i][j]= RTools::copy_str(aryFieldValue[j]);
					}
				}

				void* res = DatasetVector_wrap_write(pDS, strDtName.c_str(), strDatasetType.c_str(), wrapGeo, pFieldName, nFieldCount, pFieldValues);

				for(int i=0; i<nFieldCount; i++)
				{
					wrap_delete_primitive_ary(pFieldName[i]);
				}
				delete[] pFieldName;
				pFieldName = NULL;
				for(int i=0; i<wrapGeo.nCount; i++)
				{
					for(int j=0; j<nFieldCount; j++)
					{
						wrap_delete_primitive_ary(pFieldValues[i][j]);
					}
					delete[] pFieldValues[i];
				}
				delete[] pFieldValues;
				pFieldValues = NULL;

				if(res != NULL)
				{
					return S4_DatasetVector((UGDatasetVector*)res);
				}
				else
				{
					__result = Rcpp::wrap<bool>(false); 
				}
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_append(SEXP geos, SEXP fieldNames, SEXP fieldValues, SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDatasetVector* pDataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			Rcpp::GenericVector aryGeos  = Rcpp::as<Rcpp::GenericVector>(geos);
			Rcpp::GenericVector aryFieldName = Rcpp::as<Rcpp::GenericVector>(fieldNames);
			Rcpp::GenericVector aryFieldValues = Rcpp::as<Rcpp::GenericVector>(fieldValues);
			R_xlen_t count = aryGeos.size();
			if(count > 0 && count != aryFieldValues.size())
			{
				__result = Rcpp::wrap<bool>(false);
			}
			else
			{
				Wrap_Geometrys wrapGeo;
				wrapGeo.pGeos  = new UGGeometry*[aryFieldValues.size()];
				wrapGeo.nCount = aryFieldValues.size();
				if(count >0 )
				{
					for(int i=0; i<count; i++)
					{
						wrapGeo.pGeos[i] = (UGGeometry*)EXTPTR_PTR(aryGeos[i]);
					}
				}
				else
				{
					for(int i=0; i<wrapGeo.nCount; i++)
					{
						wrapGeo.pGeos[i] = NULL;
					}
				}

				int nFieldCount = aryFieldName.size();
				char** pFieldName = new char*[nFieldCount];
				for(int i=0; i<nFieldCount; i++)
				{
					pFieldName[i] = RTools::copy_str(aryFieldName[i]);
				} 		
				char*** pFieldValues = new char**[wrapGeo.nCount];
				for(int i=0; i<wrapGeo.nCount; i++)
				{
					pFieldValues[i] = new char*[nFieldCount];
					Rcpp::CharacterVector aryFieldValue = Rcpp::as<Rcpp::CharacterVector>(aryFieldValues[i]);
					for(int j=0; j<nFieldCount; j++)
					{
						pFieldValues[i][j]  = RTools::copy_str(aryFieldValue[j]);
					}
				}
				UGbool isResult = DatasetVector_wrap_append(pDataset, wrapGeo, pFieldName, nFieldCount, pFieldValues);
				for(int i=0; i<nFieldCount; i++)
				{
					wrap_delete_primitive_ary(pFieldName[i]);
				}
				delete[] pFieldName;
				pFieldName = NULL;
				for(int i=0; i<wrapGeo.nCount; i++)
				{
					for(int j=0; j<nFieldCount; j++)
					{
						wrap_delete_primitive_ary(pFieldValues[i][j]);
					}
					delete[] pFieldValues[i];
				}
				delete[] pFieldValues;
				pFieldValues = NULL;
				__result = Rcpp::wrap<bool>(isResult); 
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetVector_create_fields(SEXP pointer, SEXP infos)
	{
		BEGIN_RCPP
			SEXP __result = NULL;
		UGDatasetVector* pDataset = (UGDatasetVector*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			Rcpp::GenericVector fieldInfos = Rcpp::as<Rcpp::GenericVector>(infos);
			int count = fieldInfos.size();
			Wrap_FieldInfos wrapFieldInfos;
			wrapFieldInfos.nCount = count;
			wrapFieldInfos.pFieldInfo = new Wrap_FieldInfo*[count];

			for(int i=0; i<count; i++){
				Rcpp::GenericVector fieldInfo  = Rcpp::as<Rcpp::GenericVector>(fieldInfos[i]);
				Wrap_FieldInfo* pFieldInfo = new Wrap_FieldInfo();
				pFieldInfo->name  = RTools::copy_str(fieldInfo["name"]);
				pFieldInfo->type  = RTools::copy_str(fieldInfo["type"]);
				pFieldInfo->caption  = RTools::copy_str(fieldInfo["caption"]);
				pFieldInfo->defaultValue  = RTools::copy_str(fieldInfo["default"]);
				pFieldInfo->bRequired  = Rcpp::as<bool>(fieldInfo["required"]);
				pFieldInfo->bSystem  = Rcpp::as<bool>(fieldInfo["systemField"]);
				pFieldInfo->maxLength  =  Rcpp::as<int>(fieldInfo["maxLength"]);
				wrapFieldInfos.pFieldInfo[i] = pFieldInfo;
			}
			UGbool bRes =  DatasetVector_wrap_createFields(pDataset, wrapFieldInfos);
			for(int i=0; i<wrapFieldInfos.nCount; i++)
			{
				Wrap_FieldInfo* pF = wrapFieldInfos.pFieldInfo[i];
				wrap_delete_primitive_ary(pF->name);
				wrap_delete_primitive_ary(pF->caption);
				wrap_delete_primitive_ary(pF->type);
				wrap_delete_primitive_ary(pF->defaultValue);
				delete pF;
			}
			delete[] wrapFieldInfos.pFieldInfo;
			__result =  Rcpp::wrap<bool>(bRes);
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetRaster_Read_RasterInfo(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			Wrap_RasterInfo rasterInfo;
			if(DatasetRaster_wrap_read_rasterInfo(pDataset, rasterInfo))
			{
				Rcpp::GenericVector res(5);
				res[0] = Rcpp::wrap<int>((int)rasterInfo.nWidth);
				res[1] = Rcpp::wrap<int>((int)rasterInfo.nHeight);
				res[2] = Rcpp::wrap(rasterInfo.dNoValue);
				res[3] = RTools::wrap_str(rasterInfo.pixelFormat);
				Rcpp::NumericVector bounds(4);
				bounds[0] = rasterInfo.bounds[0];
				bounds[1] = rasterInfo.bounds[1];
				bounds[2] = rasterInfo.bounds[2];
				bounds[3] = rasterInfo.bounds[3];
				res[4] = bounds;
				__result = Rcpp::wrap(res);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetRaster_Read_Pixels(SEXP pointer)
	{
		BEGIN_RCPP
			SEXP __result;
		UGDataset* pDataset = (UGDataset*) EXTPTR_PTR(pointer);
		if(pDataset != NULL)
		{
			Wrap_Pixels pixels;
			if(DatasetRaster_wrap_read_pixels(pDataset, pixels))
			{
				R_xlen_t nCount = (R_xlen_t)pixels.nWidth * (R_xlen_t)pixels.nHeight;
				Rcpp::NumericVector xs(nCount);
				Rcpp::NumericVector ys(nCount);
				Rcpp::NumericVector vs(nCount);
				for(R_xlen_t i=0; i<nCount; i++)
				{
					xs[i] = pixels.pxs[i];
					ys[i] = pixels.pys[i];
					if(pixels.pvs[i] == UG_DBLMIN)
					{
						vs[i] = NA_REAL;
					}
					else
					{
						vs[i] = pixels.pvs[i];
					}
				}
				wrap_delete_primitive_ary(pixels.pxs);
				wrap_delete_primitive_ary(pixels.pys);
				wrap_delete_primitive_ary(pixels.pvs);
				Rcpp::GenericVector res(3);
				res[0] = xs;
				res[1] = ys;
				res[2] = vs;
				__result = Rcpp::wrap(res);
			}
			else
			{
				__result = Rcpp::wrap<bool>(false);
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}

	RcppExport SEXP R_DatasetRaster_Writer_pixelDataFrame(SEXP pointer, SEXP name, SEXP rc,
		SEXP width, SEXP height,SEXP pixelFormat, SEXP gridIndex, SEXP values)
	{
		BEGIN_RCPP
			SEXP __result;

		UGDataSource* pDatasource = (UGDataSource*) EXTPTR_PTR(pointer);
		if(pDatasource != NULL)
		{
			string strDtName = RTools::as_str(name);
			Rcpp::NumericVector aryRc(rc);
			double rcBounds[4];
			rcBounds[0] = aryRc[0];
			rcBounds[1] = aryRc[1];
			rcBounds[2] = aryRc[2];
			rcBounds[3] = aryRc[3];

			string strPixelFormat = RTools::as_str(pixelFormat);

			int nWidth = Rcpp::as<int>(width);
			int nHeight = Rcpp::as<int>(height);
			Rcpp::IntegerVector aryGridIndex(gridIndex);
			Rcpp::NumericVector aryPixel(values);
			if(aryGridIndex.size() != aryPixel.size())
			{
				__result = Rcpp::wrap<bool>(false);
			}
			else
			{
				int count = aryGridIndex.size();
				int* pGridIndex = new int[count];
				double* pPixel = new double[count];
				for(int i=0; i<count; i++)
				{
					pGridIndex[i] = aryGridIndex[i];
					if(Rcpp::NumericVector::is_na(aryPixel[i]))
					{
						pPixel[i] = UG_DBLMIN;
					}
					else
					{
						pPixel[i] = aryPixel[i];
					}
				}

				void* pRes = DatasetRaster_wrap_writer_pixelDataFrame(pDatasource, strDtName.c_str(), rcBounds,
					nWidth, nHeight, strPixelFormat.c_str(), pGridIndex, pPixel, count);

				delete[] pGridIndex;
				pGridIndex = NULL;
				delete[] pPixel;
				pPixel = NULL;
				
				if(pRes != NULL)
				{
					__result = S4_DatasetRaster((UGDatasetRaster*)pRes);
				}
				else
				{
					__result = Rcpp::wrap<bool>(false);
				}
			}
		}
		else
		{
			__result = Rcpp::wrap<bool>(false);
		}
		return __result;
		END_RCPP
	}
}
